package com.mumulx.check.server;

import com.mumulx.check.redis.util.FastDfsClientUtil;
import lombok.extern.slf4j.Slf4j;
import nxopen.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.*;
import java.util.stream.Collectors;

/*
 *  Created by IntelliJ IDEA.
 *  User: 木木
 *  Date: 2020/9/12
 *  Time: 15:48
 */
@Component
@Slf4j
public class ExecuteChecker {

    @Resource
    FastDfsClientUtil fastDfsClientUtil;

    @Value("${nx.partinitimage}")
    private String partInitImage;
    @Value("${nx.checkmate-log-xsl-filename}")
    private String checkmateLogXslFilename;
    @Value("${nx.clxfid}")
    private int clxfid;


    /***
     * 从fastdfs中下载文件
     * @author mumulx
     * @creed: mumulx编写
     * @email: 2606964863@qq.com
     * @date 2020/11/4 17:34
     * @param parts  fastdfs中文件的存储位置  key：该条测试文件的记录id  value：存储位置
     * @param downloadPath 文件下载本机的位置
     * @return java.util.List<java.lang.String>  返回结果是一个不包含后缀的文件绝对路径
     *
     *
     * 重新new一个newmap而不是去更新oldmap中的值---涉及到java传值的知识点了
     */
    public Map<Integer, String> downloadPart(Map<Integer, String> parts,String downloadPath) throws IOException {
        //List<String> filePath = new ArrayList<>();
        Map<Integer, String> filePath = new HashMap<>();
        File prtSaveFile = new File(downloadPath);
        /*创建文件目录*/
        if (!prtSaveFile.exists()) {
            log.info("创建了文件夹"+prtSaveFile.getPath());
            prtSaveFile.mkdirs();
        }
        for (Integer a :parts.keySet() ) {
            /*group1/M00/00/00/wKgCgF-iYF2AEICCAAFqpRpsOlQ17.prt**/
            String partName = parts.get(a);
            byte[] bytes = fastDfsClientUtil.download_bytes(partName);
            //获取元数据 ---里面存储了文件本来的名字
            String value = fastDfsClientUtil.getMetadata(partName)[0].getValue();
            //仅要文件名
            String fileName = value.substring(0, value.lastIndexOf("."));

            //fastDfsClientUtil.get
            //文件名组成：记录id.prt
            String filename=downloadPath+fileName;
            FileOutputStream fos = new FileOutputStream(new File(filename+".prt"));
            fos.write(bytes);
            fos.close();
            log.info("---"+fileName+".prt部件已经下载成功");
            //filePath.add(filename);//记录文件地址
            //filePath.put(a, filename);
            filePath.put(a,filename);
        }
        return filePath;
    }


    public Map<Integer, String> uploadResultFile(Map<Integer, String> partSaveUrl,String checkxslPath) {
        //Map<Integer, String> ans = new HashMap<>();
        //上传.xml结果文件
        for (int a : partSaveUrl.keySet()) {
            String s = partSaveUrl.get(a);
            String xml = fastDfsClientUtil.uploadFile(s + ".xml", "xml");
            partSaveUrl.put(a, xml);
        }
        //上传样式文件.xsl
        String xsl = fastDfsClientUtil.uploadFile( checkxslPath+checkmateLogXslFilename , "xsl");
        partSaveUrl.put(clxfid,xsl);

        log.info("结果文件已经上传成功，记录为："+partSaveUrl.toString());
        return partSaveUrl;
    }
    /**
     * 执行prt文件的测试
     * @author mumulx
     * @creed: mumulx编写
     * @email: 2606964863@qq.com
     * @date 2020/9/12 16:46
     * @param parts    部件位置  如D:\\workplace\\nx\\prt\\model1.prt
     * @param rules    测试的规则  如%mqc_check_feature_rollback
     * @param resultFilesDir   测试结果保存的位置  如D:\\workplace\\nx\\log\\
     * @return nxopen.Validation.Result  返回结果位测试的状态
     *
     */
    public int execute(Map<Integer,String> partSaveUrl,List<String> rules,String resultFilesDir) throws RemoteException, NXException {
        //获取value集合---测试部件的存储位置
        /*不能强制转换*/
        //List<String> values = (List<String>) partSaveUrl.values();
        List<String> parts = partSaveUrl.values().stream().collect(Collectors.toList());
        log.info("----开始部件检查");
        Validation.Result result=null;
        int rs=-1;
        //try {

            Session theSession = SingleNxSession.getInstance();
            //NXRemotableObject.RemotingProtocol remotingProtocol = NXRemotableObject.RemotingProtocol.create();
            //Session theSession = (Session) SessionFactory.get("Session", remotingProtocol);

            log.info("获取nxsession成功"+theSession);
            nxopen.validate.Validator [] validators1 ;
            validators1 = theSession.validationManager().findValidator("Check-Mate");
            nxopen.validate.ValidatorOptions validatorOptions1;

            validatorOptions1 = validators1[0].validatorOptions();

            validatorOptions1.setSkipChecking(false);

            validatorOptions1.setSkipCheckingDontLoadPart(false);

            validatorOptions1.setSaveResultInTeamcenter(nxopen.validate.ValidatorOptions.SaveModeTypes.DO_NOT_SAVE);

            validatorOptions1.setSavePartFile(nxopen.validate.ValidatorOptions.SaveModeTypes.DO_NOT_SAVE);

            validatorOptions1.setSaveResultInPart(false);

            validatorOptions1.setLogFileMode(nxopen.validate.ValidatorOptions.LogModeTypes.LOG_PER_PART);//一个部件一个结果文件
            validatorOptions1.setGenerateLogFile(true);//保存结果文件
            //validatorOptions1.setLogFileDirectory("D:\\workplace\\nx\\log\\");//结果文件保存位置

            validatorOptions1.setLogFileDirectory(resultFilesDir);//结果文件保存位置
            validators1[0].clearPartNodes();
            for(String s:parts){
                validators1[0].appendPartNode(s+".prt");
            }
            for (String s:rules){
                validators1[0].appendCheckerNode("%"+s);
            }
/*
            validators1[0].appendPartNode("D:\\workplace\\nx\\prt\\model1.prt");
            validators1[0].appendPartNode("D:\\workplace\\nx\\prt\\model2.prt");
            validators1[0].appendPartNode("D:\\workplace\\nx\\prt\\model3.prt");
*/
        /*    validators1[0].appendCheckerNode("%mqc_check_feature_rollback");
            validators1[0].appendCheckerNode("%mqc_check_early_chamfer_blend");
*/
            log.info("准备提交测试了");
            result=validators1[0].commit();
        /*}catch (Exception e){
            log.error("部件检测失败！");
            e.printStackTrace();
            result= Validation.Result.FAILED;
        }finally {
            log.info("---文件测试信息----");
            log.info(parts.toString());
            log.info(rules.toString());
            log.info(resultFilesDir);
        }*/
        if (Validation.Result.PASS == result) {
            rs = Validation.Result._PASS;
        } else if (result == Validation.Result.WARNING) {
            rs = Validation.Result._WARNING;
        } else if (result == Validation.Result.FAILED) {
            rs = Validation.Result._FAILED;
        } else if (result == Validation.Result.UNKNOWN) {
            rs = Validation.Result._UNKNOWN;
        } else if (result == Validation.Result.SKIPPED) {
            rs = Validation.Result._SKIPPED;
        } else {
            rs = -1;
        }
        log.info("----=====文件最终测试结果为"+rs);
        return rs;
    }


    public void deleteAllFiles(File directory) {
        /*不是文件夹就删除*/
        if (!directory.isDirectory()) {
            directory.delete();
        } else {
            File[] files = directory.listFiles();
            // 空文件夹
            if (files.length == 0) {
                directory.delete();
                return;
            }
            // 删除子文件夹和子文件
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteAllFiles(file);
                } else {
                    file.delete();
                }
            }
            // 删除文件夹本身
            directory.delete();
        }
    }
    /*
     * 获取部件的预览图
     * @author mumulx
     * @creed: mumulx编写
     * @email: 2606964863@qq.com
     * @date 2020/11/5 16:11
     * @param partPath 文件在本地的存储位置--不加后缀：D:\workplace\nxdownload\9\122\285\model1
     * @return boolean
     *
     */
    private String getPrtPreviewImage(String partPath) throws NXException, IOException {

        Session theSession = SingleNxSession.getInstance();
        theSession.parts().openActiveDisplay(partPath+".prt", DisplayPartOption.ALLOW_ADDITIONAL);
        Part workPart = theSession.parts().work();
        workPart.modelingViews().workView().orient(View.Canned.TRIMETRIC, View.ScaleAdjustment.FIT);
        BasePart.PreviewImageData previewImage = workPart.getPreviewImage();

        int height = previewImage.height;
        int width = previewImage.width;
        int[] pixels=previewImage.pixels;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        File f = new File(partPath+".png");
        for(int x = 0; x < width; x++){
            for(int y = 0; y < height; y++){
                image.setRGB(x, y, pixels[y*width+x]);
            }
        }

        ImageIO.write(image, "PNG", f);
        workPart.close(BasePart.CloseWholeTree.FALSE, BasePart.CloseModified.USE_RESPONSES, theSession.parts().newPartCloseResponses());


        return partPath+".png";
    }

    public Map<Integer, String> getAndUploadPrtPreviewImages(Map<Integer,String> partSaveUrl) {
        Map<Integer, String> ans = new HashMap<>();
        //本地png文件
        String prtPreviewImage = null;
        //最终结果
        String imageSavePath=null;
        //png上传位置
        String pngUploadPath = null;
        for (Integer a:partSaveUrl.keySet()) {
            String value = partSaveUrl.get(a);
            /**两种情况--我们最终总会返回一个预览图的实际存储位置---出错时--给出默认值++++或存储正式的地址
             * 1. 获取文件预览图时失败了--或发生了异常---就不会继续执行文件上传的步骤
             *
             * 2.预览图获取成功---但是文件上传却失败了
             *
             * **/
            try {
                //获取文件预览图存储在本机的位置
                prtPreviewImage = getPrtPreviewImage(value);
                //图片文件上传后的存储位置
                pngUploadPath = fastDfsClientUtil.uploadFile(prtPreviewImage, "png");
            } catch (NXException e) {
                log.error("NX出错----");
                e.printStackTrace();
            } catch (RemoteException e) {
                log.error("NX服务出错----");
                e.printStackTrace();
            } catch (IOException e) {
                log.error("图片文件写入失败-----");
                e.printStackTrace();
            }finally {
                //当image没有预览图或获取预览图失败时----存储预览图文件失败时---给出默认的图片存储位置
                if ("".equals(prtPreviewImage) || prtPreviewImage == null||pngUploadPath == null || "".equals(pngUploadPath)) {
                    imageSavePath = partInitImage;
                }else {
                    imageSavePath = pngUploadPath;
                }
            }
            ans.put(a, imageSavePath);
        }
        return ans;

    }

}
